<template>
  <el-main>
    <el-card shadow="never" header="定位SQL错误位置">
      <el-row>
        <el-form layout="inline">
          <el-form-item label="报错SQL下标位置">
            <el-input-number v-model="pos"></el-input-number>
          </el-form-item>
        </el-form>
      </el-row>
      <el-row>
        <scCodeEditor
          ref="codeEditorRef"
          v-model="showContent"
          mode="sql"
          :extensions="extensions"
        ></scCodeEditor>
      </el-row>
    </el-card>
  </el-main>
</template>

<script setup>
import { ref, onMounted, watch, onBeforeUnmount, toRaw, useTemplateRef } from 'vue'
import scCodeEditor from '@/components/scCodeEditor'

import { ViewPlugin, Decoration, EditorView } from '@codemirror/view'
import { StateEffect } from '@codemirror/state' // <-- 1. 导入 StateEffect

const codeEditorRef = useTemplateRef('codeEditorRef')
const rangesRef = ref([
  { from: 0, to: 1 },
  { from: 1, to: 2 },
  { from: 2, to: 3 }
])
// 定义一个自定义的 Effect，用于通知插件更新
const setHighlightEffect = StateEffect.define()

let highlightPlugin = ViewPlugin.fromClass(
  class {
    constructor(view) {
      this.decorations = this.buildDecorations(view, toRaw(rangesRef.value))
    }
    update(update) {
      // 检查本次事务中是否包含我们定义的 Effect
      const hasHighlightEffect = update.transactions.some((tr) =>
        tr.effects.some((effect) => effect.is(setHighlightEffect))
      )

      // 如果 Effect 被触发，或者文档本身发生了变化，就重新计算装饰
      if (hasHighlightEffect || update.docChanged) {
        this.decorations = this.buildDecorations(update.view, toRaw(rangesRef.value))
      }
    }
    buildDecorations(view, ranges) {
      if (!ranges || ranges.length === 0) {
        return Decoration.none // 如果没有范围，返回空装饰
      }
      const doc = view.state.doc
      const decorations = []
      const decoration_yellow = Decoration.mark({
        class: 'cm-highlight-by-index-yellow' // 定义 CSS 类名
      })

      const decoration_red = Decoration.mark({
        class: 'cm-highlight-by-index-red' // 定义 CSS 类名
      })
      decorations.push(
        decoration_yellow.range(ranges[0].from >= 0 ? ranges[0].from : 0, ranges[0].to)
      )
      decorations.push(decoration_red.range(ranges[1].from, ranges[1].to))
      decorations.push(
        decoration_yellow.range(
          ranges[2].from,
          ranges[2].to <= doc.length ? ranges[2].to : doc.length
        )
      )

      return Decoration.set(decorations)
    }
  },
  {
    decorations: (v) => v.decorations
  }
)

// 定义高亮样式
const highlightByIndexTheme = EditorView.theme({
  '.cm-highlight-by-index-red': {
    backgroundColor: 'rgba(255, 0, 0, 0.3)'
  },
  '.cm-highlight-by-index-yellow': {
    backgroundColor: 'rgba(255, 255, 0, 0.3)'
  }
})

const extensions = [highlightPlugin, highlightByIndexTheme]

const showContent = ref(`WITH tem_dp0001 AS (
    SELECT
        DWKHH,--单位客户号
            (CASE
            WHEN (length(ZZJGDM) = 18 AND DMLX = '0')
            THEN ZZJGDM
            ELSE ''
        END ) AS ZZJGDM, --组织机构代码
        DWMC, --组织机构名称
        DWFXR --单位发薪日
    FROM
        ods.ods_cz_dlrundb_dp0001_ddf
    WHERE
        DWXZ in ('30', '31', '32', '33', '39') --30-国有企业,31-城镇集体企业,32-外商投资企业,33-城镇私营企业,39-其他城镇企业
        AND dt = '20250101'
)`)

const pos = ref(0)

watch(pos, () => {
  if (pos.value > 0 && pos.value < showContent.value.length) {
    rangesRef.value = [
      { from: pos.value - 2, to: pos.value },
      { from: pos.value, to: pos.value + 1 },
      { from: pos.value + 1, to: pos.value + 3 }
    ]
    codeEditorRef.value.dispatch({
      effects: setHighlightEffect.of(null)
    })
  }
})
</script>

<style scoped></style>
